#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#define MAXSIZE     5000

struct id_struct {
char yourId[50], friendId[50];
};

void end(char *s)
{
  perror(s);
  exit(1);
}

void assertGreaterThanInt(char* testName, const int expected, const int actual);
void assertEqualsInt(char* testName, const int expected, const int actual);
void test_recieve_message();
void *recieve_message( );

//Main function
int main(int argc, char* argv[])
{
	if(argc == 2 && strcmp(argv[1], "--test") == 0 )
	{
		printf("Starting tests...\n");

		test_recieve_message();	

		printf("All tests passed.\n");
	}
	struct id_struct ids;
     	pthread_t recieverThread;

	//Get user inputs like their chat id and id of friend	
	printf("Enter your chat id: ");
	scanf("%[^\n]",ids.yourId);
	getchar();
	ids.yourId[49] = '\0';
	printf("Enter your friends chat id: ");
	scanf("%[^\n]",ids.friendId);
	ids.friendId[49] = '\0';
	getchar();
	printf("\n%s you are talking to %s\n", ids.yourId, ids.friendId);
	printf("Hit 'Enter' to exit chat.\n");
	//Create thread for receiving messages
	int iret2 = pthread_create( &recieverThread, NULL, recieve_message, (void *)&ids);
	printf("%s >", ids.yourId);

    	char buf[MAXSIZE];
    	if(mkfifo(ids.friendId, 0666) < 0 && (errno != EEXIST))
		end("Error creating friend's named pipe");

	/* Open the named pipe for writing */
	int wrfd = open(ids.friendId, O_WRONLY);

	while(scanf("%[^\n]",buf) != '\0')
	{
	    	getchar();
		char message[550];
		strcpy(message, ids.yourId);
		strcat(message, " wrote: ");
		strcat(message, buf);
		printf("%s >",ids.yourId);
		buf[MAXSIZE-1] ='\0';
		write(wrfd, message, strlen(message));
		buf[0] = '\0';
	}
     	printf("Terminating...\n");
	close(wrfd);
     	exit(0);
}

///Function for receiving messages
void *recieve_message(void* ids)
{
printf("enter");
	struct id_struct * chatIds = (struct id_struct *) ids;
	char buf[MAXSIZE];

   	/* Create the named pipe for reading */
    	if(mkfifo(chatIds->yourId, 0666) < 0 && errno != EEXIST)
		end("Error creating name pipe for reading your messages");
 printf("tet");
     	/* Open the named pipe for reading */
    	int rdfd = open(chatIds->yourId, O_RDONLY);
printf("teta");
	while(1)
	{
		/* Read from the pipe */
	    	int numread = read(rdfd, buf, sizeof(buf));
		buf[numread] = '\0';
	   	if(numread != 0)
			fprintf(stderr, "\n%s\n%s >",buf, chatIds->yourId);
	}
	close(rdfd);
}

/**************************** Test cases ***********************************/

void test_recieve_message()
{
	struct id_struct ids;
  	pthread_t recieverThread;
	strcpy(ids.yourId, "Shikha");
	strcpy(ids.friendId, "Maniza");
	int iret2 = pthread_create( &recieverThread, NULL, recieve_message, (void *)&ids);
	assertEqualsInt("Receive message test.", 0, iret2);
}

void assertEqualsInt(char* testName, const int expected, const int actual)
{
	if(expected != actual)
	{
		printf("Expected <%d> but was <%d> in %s.\n", expected, actual, testName);
		exit(1);	
	}
}

void assertGreaterThanInt(char* testName, const int expected, const int actual)
{
	if(expected >= actual)
	{
		printf("Expected greater than <%d> but was <%d> in %s.\n", expected, actual, testName);
		exit(1);	
	}
}
